import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.util.LinkedList;

import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
import FlexTrade.AuctionPrimitiveData;
import FlexTrade.AuctionStates;
import FlexTrade.BidPriceData;
import FlexTrade.CustomerData;
import FlexTrade.FlexTradeUtils;
import FlexTrade.IAuction;

import javax.swing.JComboBox;
import javax.swing.GroupLayout.Alignment;
import javax.swing.GroupLayout;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.DefaultComboBoxModel;

import net.jini.core.lookup.ServiceMatches;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.DiscoveryEvent;
import net.jini.discovery.DiscoveryListener;
import net.jini.discovery.LookupDiscovery;
import javax.swing.JButton;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * CustomerUI.java
 *
 * Created on May 10, 2012, 10:54:17 PM
 */
/**
 *
 * @author hieuht
 * Main user interface for customer that wants to participart in auction
 */
public class CustomerUI extends javax.swing.JFrame implements DiscoveryListener{
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static String POLICY_FILE = "/home/hieuht/Eclipse/workspaceJEE/Customer/src/policy.txt";
    /** Creates new form CustomerUI */
    public CustomerUI() {
    	this.setTitle("FlexTrade Customer UI");
        model = new DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null}
            },
            new String [] {
                "ID", "Product", "Provider", "Type", "Cur. Offer", "Status"
            }
        );
        initComponents();
        customerData = new CustomerData();
        logedIn = false;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jScrollPane2 = new javax.swing.JScrollPane();
        txtAuctionLog = new javax.swing.JTextArea();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        btnJoinAuction = new javax.swing.JButton();
        btnLogin = new javax.swing.JButton();
        btnRefresh = new javax.swing.JButton();
        btnExit = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        tblCurrentAuctions = new javax.swing.JTable();
        tblCurrentAuctions.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tblCurrentAuctionsMouseClicked(evt);
            }
        });
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        txtAuctionLog.setColumns(20);
        txtAuctionLog.setRows(5);
        jScrollPane2.setViewportView(txtAuctionLog);

        jLabel1.setText("Current active auctions");

        jLabel2.setText("Auction Log");

        btnJoinAuction.setText("Join Auction");
        btnJoinAuction.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnJoinAuctionActionPerformed(evt);
            }
        });

        btnLogin.setText("Login");
        btnLogin.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnLoginActionPerformed(evt);
            }
        });
        
        btnNewCustomer = new JButton("New Customer");
        btnNewCustomer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnNewCustomerActionPerformed(evt);
            }
        });

        btnRefresh.setText("Refresh");
        btnRefresh.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnRefreshActionPerformed(evt);
            }
        });

        btnExit.setText("Exit");
        btnExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnExitActionPerformed(evt);
            }
        });

 
        jScrollPane1.setViewportView(tblCurrentAuctions);
        
        cboProduct = new JComboBox();
        
        cboProduct.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            	cboProductActionPerformed(evt);
            }
        });

        cboProduct.setModel(new DefaultComboBoxModel(new String[] {"TV LCD", "Laptop", "Camera", "Mobile Phone"}));
        


        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        layout.setHorizontalGroup(
        	layout.createParallelGroup(Alignment.LEADING)
        		.addGroup(layout.createSequentialGroup()
        			.addContainerGap()
        			.addGroup(layout.createParallelGroup(Alignment.LEADING)
        				.addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 645, Short.MAX_VALUE)
        				.addComponent(jScrollPane2, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 645, Short.MAX_VALUE)
        				.addGroup(layout.createSequentialGroup()
        					.addComponent(btnLogin, GroupLayout.PREFERRED_SIZE, 89, GroupLayout.PREFERRED_SIZE)
        					.addGap(27)
        					.addComponent(btnNewCustomer)
        					.addPreferredGap(ComponentPlacement.RELATED, 26, Short.MAX_VALUE)
        					.addComponent(btnJoinAuction)
        					.addGap(52)
        					.addComponent(btnRefresh, GroupLayout.PREFERRED_SIZE, 89, GroupLayout.PREFERRED_SIZE)
        					.addGap(38)
        					.addComponent(btnExit, GroupLayout.PREFERRED_SIZE, 90, GroupLayout.PREFERRED_SIZE))
        				.addComponent(jLabel2)
        				.addGroup(layout.createSequentialGroup()
        					.addComponent(jLabel1)
        					.addPreferredGap(ComponentPlacement.RELATED, 336, Short.MAX_VALUE)
        					.addComponent(cboProduct, GroupLayout.PREFERRED_SIZE, 144, GroupLayout.PREFERRED_SIZE)))
        			.addContainerGap())
        );
        layout.setVerticalGroup(
        	layout.createParallelGroup(Alignment.LEADING)
        		.addGroup(layout.createSequentialGroup()
        			.addGap(18)
        			.addGroup(layout.createParallelGroup(Alignment.BASELINE)
        				.addComponent(jLabel1)
        				.addComponent(cboProduct, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
        			.addPreferredGap(ComponentPlacement.UNRELATED)
        			.addComponent(jScrollPane1, GroupLayout.PREFERRED_SIZE, 170, GroupLayout.PREFERRED_SIZE)
        			.addGap(18)
        			.addComponent(jLabel2)
        			.addPreferredGap(ComponentPlacement.RELATED)
        			.addComponent(jScrollPane2, GroupLayout.PREFERRED_SIZE, 126, GroupLayout.PREFERRED_SIZE)
        			.addGap(38)
        			.addGroup(layout.createParallelGroup(Alignment.BASELINE)
        				.addComponent(btnLogin)
        				.addComponent(btnExit)
        				.addComponent(btnRefresh)
        				.addComponent(btnJoinAuction)
        				.addComponent(btnNewCustomer))
        			.addContainerGap(27, Short.MAX_VALUE))
        );
        getContentPane().setLayout(layout);

        pack();
    }// </editor-fold>

    private void tblCurrentAuctionsMouseClicked(java.awt.event.MouseEvent evt) {
    	if(!this.logedIn) {		//do nothing when provider has not logged in yet
    		return;
    	}
    }
    
    private void cboProductActionPerformed(java.awt.event.ActionEvent evt){
    	if(!this.logedIn) {
    		System.out.println("Customer not yet login");
    		return;
    	}
    	//remove all row in the table
    	model.setRowCount(0);
    	tblCurrentAuctions.setModel(this.model);
    	//remove all existing auctions in the list and create a new list
    	currentAuctions = new LinkedList<AuctionPrimitiveData>();
    	LookupDiscovery discover = null;
    	try {
    		discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
    	} catch(Exception e) {
    		System.err.println(e.toString());
    	}
    	discover.addDiscoveryListener(this);

    }
    
    private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {                                           
        // TODO add your handling code here:
    	if(!this.logedIn) {
    		JOptionPane.showMessageDialog(null, "You have to login before using this function.");
    		return;
    	}
    	refreshAuctionsTable();

    }                    
    
    public void refreshAuctionsTable(){
    	//remove all row in the table
    	model.setRowCount(0);
    	tblCurrentAuctions.setModel(this.model);
    	//remove all existing auction in the list and create a new list
    	currentAuctions = new LinkedList<AuctionPrimitiveData>();
    	LookupDiscovery discover = null;
    	try {
    		discover = new LookupDiscovery(LookupDiscovery.ALL_GROUPS);
    	} catch(Exception e) {
    		System.err.println(e.toString());
    		return;
    	}
    	discover.addDiscoveryListener(this);    	
    }
    

    private void btnExitActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
        System.exit(1);
    }

    private void btnJoinAuctionActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
    	if(!this.logedIn) {
    		JOptionPane.showMessageDialog(null, "You have to login before using this function.");
    		return;
    	}
        customer = new Customer(customerData);
        customer.setCustomerUI(this);
        
    	this.customer.setTextField(this.txtAuctionLog);	//set the text field that will show notification from customer object
    	String selectedUniqueAuctionID;
    	int auctionType = -1;
    	int index = 0;	//index of selected auction in the list of auctions
    	int selectedRow = tblCurrentAuctions.getSelectedRow();
    	//get the auction ID and aution type from table
		selectedUniqueAuctionID = (String)tblCurrentAuctions.getValueAt(selectedRow, 0);
		try{
			//iterate through list of auctions to find out the one that customer wants to join
    		for(int i=0; i<currentAuctions.size(); i++) {
    			if(currentAuctions.get(i).uniqueAuctionID.equals(selectedUniqueAuctionID)) {
    				index = i;
    				auctionType = currentAuctions.get(i).auctionType;
    				this.customer.joinRequestToAuction(selectedUniqueAuctionID);
    		    	//add information of this auction to customer object
    		    	this.customer.setAuctionPrimitiveData(currentAuctions.get(i));
    				break;
    			}
    		}
    	} catch(Exception e){
    		e.printStackTrace();
    	}			

		//if(strAuctionType.equals("Dutch")){		//Dutch auction
		if(auctionType == IAuction.DUTCH_AUCTION_TYPE){		//Dutch auction
			//get the current status of this bid (updated acceptable price)
			AuctionStates auctionStates = this.customer.currentAuctionStates;
			String message = "Current offer for this auction is ";
			message = message + Float.toString(auctionStates.acceptableBidPrice);
			message = message + ". Do  you accept it?";
			//Display dialog which allows customer to accept offer from provider
			int reply = JOptionPane.showConfirmDialog(null, message, "Information", JOptionPane.YES_NO_OPTION);
			if(reply == JOptionPane.OK_OPTION){		//acccept the offer
				BidPriceData bidPriceData = new BidPriceData();
				bidPriceData.customer = this.customerData;
				bidPriceData.bidPrice = auctionStates.acceptableBidPrice;
				this.customer.acceptPriceFromProvider(bidPriceData);
			}
			
		} else {	//Vickrey and English auction
			//Display dialog which allows customer to place a bid price
	    	PlaceBidDlg placeBid = new PlaceBidDlg(this, true);
	    	placeBid.setCustomer(customer);
	    	placeBid.setAuctionPrimitiveData(currentAuctions.get(index));
	    	placeBid.setVisible(true);			
		}
    }

    private void btnLoginActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here: 
    	LogInDlg loginDlg = new LogInDlg(this, true);
    	loginDlg.setVisible(true);
    }
    
    private void btnNewCustomerActionPerformed(java.awt.event.ActionEvent evt){
    	CreateCustomer createCustomer = new CreateCustomer(this, true);
    	createCustomer.setVisible(true);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        		// install suitable security manager
        System.setProperty("java.security.policy",POLICY_FILE);
        System.setSecurityManager(new RMISecurityManager());
		System.setProperty("java.rmi.server.codebase", "http://localhost:9000/");
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(CustomerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(CustomerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(CustomerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(CustomerUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new CustomerUI().setVisible(true);
                
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JButton btnExit;
    private javax.swing.JButton btnJoinAuction;
    private javax.swing.JButton btnLogin;
    private javax.swing.JButton btnRefresh;
    private javax.swing.JButton btnNewCustomer;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTable tblCurrentAuctions;
    private javax.swing.JTextArea txtAuctionLog;
    private JComboBox cboProduct;
    // End of variables declaration
    DefaultTableModel model;
    Customer customer;
    CustomerData customerData;
    //this linked list will store all currently active auctions
    LinkedList<AuctionPrimitiveData> currentAuctions;
    public boolean logedIn;
    
    public void setCustomerData(CustomerData _customerData) {
    	this.customerData = _customerData;
    }
    
    public CustomerData getCustomerData(){
    	return this.customerData;
    }

	@Override
	public void discarded(DiscoveryEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void discovered(DiscoveryEvent arg0) {
		// TODO Auto-generated method stub
		ServiceRegistrar[] registrars = arg0.getRegistrars();
		Class[] classes = new Class[] {IAuction.class};
		ServiceTemplate template = new ServiceTemplate(null, classes, null);
		for (int n = 0; n < registrars.length; n++) {
			ServiceRegistrar registrar = registrars[n];
			ServiceMatches matches;
			try {
				matches = registrar.lookup(template, 10);
			} catch(java.rmi.RemoteException e) {
				e.printStackTrace();
				continue;
			}
			// NB: matches.totalMatches may be greater than matches.items.length
			String strProduct;
			String strAuctionType;
			AuctionPrimitiveData auctionPrimitiveData;
			AuctionStates auctionState;
			for (int m = 0; m < matches.items.length; m++) {
				IAuction auction = (IAuction) matches.items[m].service;
				try {
					auctionPrimitiveData = auction.getAuctionPrimitiveData();
					auctionState = auction.getCurrentAuctionStates();
					strProduct = (String)this.cboProduct.getSelectedItem();
					strAuctionType = null;
					if(auctionPrimitiveData.product.getProductName().equals(strProduct)) {
						switch(auctionPrimitiveData.auctionType){
						case IAuction.VICKREY_AUCTION_TYPE:	//Vickrey
							strAuctionType = "Vickrey";
							break;
						case IAuction.ENGLISH_AUCTION_TYPE:	//English
							strAuctionType = "English";
							break;
						case IAuction.DUTCH_AUCTION_TYPE:	//Dutch
							strAuctionType = "Dutch";
							break;
						}
			    		String[] rowAdded = new String[]{
			    				auctionPrimitiveData.uniqueAuctionID,	//ID
    							strProduct,	//Product
    							auctionPrimitiveData.provider.getProviderID(),	//Provider name
    							strAuctionType,	//Auction type
    							Float.toString(auctionState.acceptableBidPrice), //current acceptable price
    							auctionState.currentStatus};	//Status of this auction
			    		model.addRow(rowAdded);
			    		tblCurrentAuctions.setModel(this.model);
			    		//add this auction to the list of currently active auctions
			    		currentAuctions.add(auctionPrimitiveData);
					}
				} catch (RemoteException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
